package br.ufpe.cin.if680.lightmirror.core;

public class Iluminacao {
	protected Vetor ambiental;
	protected Vetor difusa;
	protected Vetor especular;
	protected Vetor luzTotal;
	protected Vetor v;
	protected Vetor normal;
	protected Ponto pontoReal;
	protected Parametros parametros;
	
	public Iluminacao(Parametros p) {
		ambiental = new Vetor(0,0,0);
		difusa = new Vetor(0,0,0);
		luzTotal = new Vetor(0,0,0);
		especular = new Vetor(0,0,0);
		v = new Vetor(0,0,0);
		normal = new Vetor(0,0,0);
		pontoReal = new Ponto(0,0,0);
		this.parametros = p;
	}
	
	public Vetor calcularLuz(int fonteDeLuz) {
		Vetor il = parametros.getIl()[fonteDeLuz]; //TODO Adicionar multiplas fontes de luz
		Ponto pl = parametros.getPl()[fonteDeLuz];
		
		Vetor nulo = new Vetor(0,0,0);			// vetor que indica a direção da luz
		Vetor luz = pl.subtracao(this.pontoReal);			// componente ambiental
	    this.ambiental = parametros.getIa().produtoEscalar(parametros.getKa());	//normalizando o vetor V
	    this.v.normalizar();					//normalizando o vetor N
	    this.normal.normalizar();				//normalizando o vetor V
		luz.normalizar();
	        
		// calculando o produto interno
	    double teste = this.v.produtoInterno(this.normal);

		if(teste < 0) {
			this.normal = this.normal.produtoEscalar(-1); 
	    }

		// calcula o produto interno entre a luz e a normal do ponto
		double prodInt = this.normal.produtoInterno(luz);

	    if(prodInt < 0){
	        this.difusa = nulo;  
			this.especular = nulo; 
		} else {
			Vetor r = (this.normal.produtoEscalar(2 * prodInt)).subtracao(luz);
			r.normalizar();

			this.difusa = ((parametros.getKd().produtoComponentes(parametros.getOd())).produtoComponentes(il)).produtoEscalar(prodInt);
			double temp = this.v.produtoInterno(r);

			if(temp < 0){
				this.especular = nulo;
			} else {
				double temp2 = Math.pow(temp, parametros.getEta());
				this.especular = il.produtoEscalar(temp2 * parametros.getKs());
			}
		}
	    return (this.ambiental.soma(this.luzTotal.soma(this.difusa.soma(this.especular))));
	}
	
	protected void iluminar(Vetor coordBaric, Triangulo tReal) {
		this.pontoReal = calcularPontoReal(coordBaric, tReal);
		this.normal = calcularNormal(coordBaric, tReal);
		this.v = new Ponto(0.0, 0.0, 0.0).subtracao(this.pontoReal);
	}
	
	protected Vetor calcularNormal(Vetor v, Triangulo t){ 
		return (t.a.normal.produtoEscalar(v.getX())).soma((t.b.normal.produtoEscalar(v.getY()))
				.soma((t.c.normal.produtoEscalar(v.getZ()))));
	}
	
	protected Ponto calcularPontoReal(Vetor v, Triangulo t){ 
		return ((t.a).produtoEscalar(v.getX())).soma(((t.b).produtoEscalar(v.getY()))
				.soma(((t.c).produtoEscalar(v.getZ()))));
	}
}
